package com.raojunxue.company.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import com.raojunxue.company.dao.AbstractDao;
import com.raojunxue.company.persist.EMF;
import com.raojunxue.company.util.PageIndex;

public abstract class AbstractDaoImpl<T extends Serializable,ID extends Serializable> implements AbstractDao<T, ID>{

	protected static final Logger log = Logger.getLogger(AbstractDaoImpl.class.getName());
	
	protected Class<T> persistClass;
	
	@SuppressWarnings("unchecked")
	public AbstractDaoImpl(){
		this.persistClass = (Class<T>) ((ParameterizedType)
				getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	
	public void delete(T t) {
		EntityManager em = EMF.getEM();
		EntityTransaction trans = em.getTransaction();
		try {
			trans.begin();
			em.remove(t);
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			trans.commit();
		}
	}

	public T findById(ID id) {
		EntityManager em = EMF.getEM();
		T t = null;
		try {
			System.out.println("id:"+id);
			t = em.find(this.persistClass, id);
		}catch(Exception e){
			e.printStackTrace();
		}
		return t;
	}

	public void save(T t) {
		EntityManager em = EMF.getEM();
		EntityTransaction trans = em.getTransaction();
		try {
			trans.begin();
			em.persist(t);
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			trans.commit();
		}
	}

	public void update(T t) {
		EntityManager em = EMF.getEM();
		EntityTransaction trans = em.getTransaction();
		try {
			trans.begin();
			em.merge(t);
		}catch(Exception e){
			e.printStackTrace();
		}finally {
			trans.commit();
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<T> list(){
		EntityManager em = EMF.getEM();
		String sql = "select c from " + this.persistClass.getName() + " c";
		List<T> ts = null;
		try{
			log.info(sql);
			ts = (List<T>) em.createQuery(sql).getResultList();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return ts;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findByProperty(String propertyName, Object value){
		EntityManager em = EMF.getEM();
		String sql = "select from " + this.persistClass.getName() + " c where c." + propertyName + "=:value";
		System.out.println(propertyName + ":" + value);
		List<T> ts = null;
		try{
			log.info(sql);
			ts = (List<T>) em.createQuery(sql)
			.setParameter("value", value).getResultList();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return ts;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> list(PageIndex pageIndex){
		EntityManager em = EMF.getEM();
		String countSql = "select count(c) from " + this.persistClass.getName() + " c";
		String selectSql = "select c from " + this.persistClass.getName() + " c";
		List<T> ts = null;
		try{
			int count = (Integer)em.createQuery(countSql).getSingleResult();
			pageIndex.setTotalRows(count);
			ts = (List<T>) em.createQuery(selectSql)
			.setFirstResult(pageIndex.getStartRow())
			.setMaxResults(pageIndex.getPageSize())
			.getResultList();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return ts;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> listOrderByProperty(PageIndex pageIndex, String PropertyName){
		EntityManager em = EMF.getEM();
		String countSql = "select count(c) from " + this.persistClass.getName() + " c";
		String selectSql = "select from " + this.persistClass.getName() + " order by " + PropertyName + " desc";
		List<T> ts = null;
		try{
			int count = (Integer)em.createQuery(countSql).getSingleResult();
			pageIndex.setTotalRows(count);
			ts = (List<T>) em.createQuery(selectSql)
			.setFirstResult(pageIndex.getStartRow())
			.setMaxResults(pageIndex.getPageSize())
			.getResultList();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return ts;
	}
	
	@SuppressWarnings("unchecked")
    public List<T> listOrderByProperty(int number, String propertyName, Object value, String orderProperty, boolean desc){
	    EntityManager em = EMF.getEM();
	    String paixu = desc?" desc":" asc";
		String selectSql = "select from " + this.persistClass.getName() + " c where c." + propertyName
            + "=:value order by " + orderProperty + paixu;
        List<T> ts = null;
        try{
            ts = (List<T>) em.createQuery(selectSql)
            .setParameter("value", value)
            .setMaxResults(number)
            .getResultList();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return ts;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> listOrderByProperty(PageIndex pageIndex, String propertyName, Object value, String orderProperty){
		EntityManager em = EMF.getEM();
		String countSql = "select count(c) from " + this.persistClass.getName() + " c where c." + propertyName
        + "=:value";
		String selectSql = "select from " + this.persistClass.getName() + " c where c." + propertyName
            + "=:value order by " + orderProperty + " desc";
        List<T> ts = null;
        try{
        	int count = (Integer)em.createQuery(countSql)
        		.setParameter("value", value).getSingleResult();
			pageIndex.setTotalRows(count);
            ts = (List<T>) em.createQuery(selectSql)
            .setParameter("value", value)
            .setFirstResult(pageIndex.getStartRow())
            .setMaxResults(pageIndex.getPageSize())
            .getResultList();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return ts;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> listOrderByProperty(PageIndex pageIndex, String propertyName, boolean asc){
		EntityManager em = EMF.getEM();
		String shunxu = asc ? " asc" : " desc";
		String countSql = "select count(c) from " + this.persistClass.getName() + " c";
		String selectSql = "select from " + this.persistClass.getName() + " c order by " + propertyName + shunxu;
        List<T> ts = null;
        try{
        	int count = (Integer)em.createQuery(countSql).getSingleResult();
			pageIndex.setTotalRows(count);
            ts = (List<T>) em.createQuery(selectSql)
            .setFirstResult(pageIndex.getStartRow())
            .setMaxResults(pageIndex.getPageSize())
            .getResultList();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return ts;
	}
	
	
	@SuppressWarnings("unchecked")
	public List<T> list(PageIndex pageIndex, int count){
		EntityManager em = EMF.getEM();
		String selectSql = "select c from " + this.persistClass.getName() + " c";
		List<T> ts = null;
		try{
			pageIndex.setTotalRows(count);
			ts = (List<T>) em.createQuery(selectSql)
			.setFirstResult(pageIndex.getStartRow())
			.setMaxResults(pageIndex.getPageSize())
			.getResultList();
		}catch (Exception e) {
			e.printStackTrace();
		}
		return ts;
	}

	@SuppressWarnings("unchecked")
	public List<T> listByProperty(PageIndex pageIndex, String propertyName,
			Object value){
		EntityManager em = EMF.getEM();
		String countSql = "select count(c) from " + this.persistClass.getName() + " c where c." + propertyName
        + "=:value";
		String selectSql = "select from " + this.persistClass.getName() + " c where c." + propertyName
            + "=:value";
        List<T> ts = null;
        try{
        	int count = (Integer)em.createQuery(countSql)
        		.setParameter("value", value)
        		.getSingleResult();
        	System.out.println(count);
			pageIndex.setTotalRows(count);
			ts = (List<T>) em.createQuery(selectSql)
				.setParameter("value", value)
				.setFirstResult(pageIndex.getStartRow())
				.setMaxResults(pageIndex.getPageSize())
				.getResultList();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return ts;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> listByProperty(PageIndex pageIndex, String propertyName,
			Object value, int count){
		EntityManager em = EMF.getEM();
		String countSql = "select count(c) from " + this.persistClass.getName() + " c where c." + propertyName
        + "=:value";
		String selectSql = "select from " + this.persistClass.getName() + " c where c." + propertyName
            + "=:value";
        List<T> ts = null;
        try{
        	int realCount = (Integer)em.createQuery(countSql)
    		.setParameter("value", value)
    		.getSingleResult();
            System.out.println(selectSql);
			pageIndex.setTotalRows(count < realCount ? count : realCount);
			ts = (List<T>) em.createQuery(selectSql)
				.setParameter("value", value)
				.setFirstResult(pageIndex.getStartRow())
				.setMaxResults(pageIndex.getPageSize())
				.getResultList();
        }catch (Exception e) {
            e.printStackTrace();
        }
        return ts;
	}
}
